package com.ljy.my_study.java.时间轮;

import com.ljy.my_study.类的加载.A;

import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Queue;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicBoolean;

/**
 * @description:
 * @author: James
 * @create: 2022-04-16 19:35
 */
public class TimeRoundMonitor extends Thread{

    private ScheduledExecutorService bossTaskExecutor;
    private ThreadPoolExecutor taskExecutor;

    private TimeRound[] rounds;

    private AtomicBoolean start=new AtomicBoolean(true);

    public TimeRoundMonitor() {
        this.bossTaskExecutor = new ScheduledThreadPoolExecutor(1);
        this.taskExecutor = new ThreadPoolExecutor(5,10,100, TimeUnit.SECONDS,
                new LinkedBlockingQueue<>());
        rounds=new TimeRound[24];
    }

    /**
     * 直接使用每秒检测一次时间间隔大
     * 同时直接sleep不能让出占用锁
     * 可以改用DelayQueue，里面使用Condition.await可以让出线程占用锁
     */
    @Override
    public void run() {
        System.out.println("TimeRoundMonitor start ...");
        while(start.get()){
            this.bossTaskExecutor.schedule(()->{
                Queue<Task> tasks=chooseTasks();
                while(tasks!=null&&!tasks.isEmpty()){
                    Task task=tasks.poll();
                    taskExecutor.execute(task);
                }
            },20,TimeUnit.MILLISECONDS);
        }
    }

    /**
     * 退出
     * @return
     */
    public boolean destory(){
        start.set(false);
        return true;
    }

    private Queue<Task> chooseTasks(){
        TimeRound timeRound=getSecondTimeRound(0,false);
        if(timeRound==null){
            return null;
        }
        return timeRound.getTasks();
    }

    /**
     * 模拟加入任务，每个任务下个时间单位都是秒
     * @param task
     */
    public void add(Task task){
        Integer second=task.getNextTime();
        TimeRound timeRound=getSecondTimeRound(second,true);
        timeRound.addTask(task);
    }


    private synchronized TimeRound getSecondTimeRound(Integer second,boolean needCreate){
        Calendar calendar=Calendar.getInstance();
        calendar.add(Calendar.SECOND,second);
        int hourIndex=calendar.get(Calendar.HOUR_OF_DAY);
        int minuteIndex=calendar.get(Calendar.MINUTE);
        int secondIndex=calendar.get(Calendar.SECOND);
        TimeRound hourTimeRound=rounds[hourIndex];
        if(hourTimeRound==null&&needCreate){
            synchronized (("hour"+hourIndex).intern()){
                if(hourTimeRound==null){
                    hourTimeRound=new TimeRound(hourIndex,TimeUnit.HOURS);
                    rounds[hourIndex]=hourTimeRound;
                }
            }
        }
        if(hourTimeRound==null){
            return null;
        }
        TimeRound minuteRound=hourTimeRound.getNext()[minuteIndex];
        if(minuteRound==null&&needCreate){
            synchronized (("minute"+minuteIndex).intern()){
                if(minuteRound==null){
                    minuteRound=new TimeRound(minuteIndex,TimeUnit.MINUTES);
                    hourTimeRound.getNext()[minuteIndex]=minuteRound;
                }
            }
        }
        if(minuteRound==null){
            return null;
        }
        TimeRound secondRound=minuteRound.getNext()[secondIndex];
        if(secondRound==null&&needCreate){
            synchronized (("second"+secondIndex).intern()){
                if(secondRound==null){
                    secondRound=new TimeRound(secondIndex,TimeUnit.SECONDS);
                    minuteRound.getNext()[secondIndex]=secondRound;
                }
            }
        }
        if(secondRound==null){
            return null;
        }
        return secondRound;
    }

    /**
     * 判断是否加入任务
     * @return
     */
    public static boolean needAdd(){
        return true;
    }
}
